package core

import (
	"animal/octopus/cache"
	"animal/octopus/common"
	"animal/octopus/orm"

	log "github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func GetTopoViewList(moduleID uint) ([]common.TopoViewInfo, error) {
	return cache.Instance().GetTopoViewList(moduleID)
}

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func CreateTopoView(db *gorm.DB, param common.CreateTopoViewParam) (uint, error) {
	// check module existence
	if _, err := cache.Instance().FindModuleByID(param.ModuleID); err != nil {
		log.WithField("param", common.MustMarshal(param)).
			Error("cannot find module")
		return 0, err
	}

	var topoViewID uint = 0

	if err := common.DB(db).Transaction(func(tx *gorm.DB) error {
		topoView, err := orm.CreateTopoView(tx, param)
		if err != nil {
			log.WithField("param", common.MustMarshal(param)).
				Error("create topo view in database failed")
			return err
		}
		if err := cache.Instance().CreateTopoView(topoView); err != nil {
			log.WithField("param", common.MustMarshal(param)).
				Error("create topo view in cache failed")
			return err
		}
		topoViewID = topoView.ID
		return nil
	}); err != nil {
		log.Error("create topo view failed")
		return 0, err
	}

	return topoViewID, nil
}

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func EditTopoView(db *gorm.DB, param common.EditTopoViewParam) error {
	topoView, err := cache.Instance().FindTopoViewByID(param.ID)
	if err != nil {
		log.WithField("ID", param.ID).Error("cannot find topo view")
		return err
	}

	if topoView.Name == topoView.Module.Name+"-topo-view" {
		log.WithField("ID", param.ID).
			Error("cannot edit default topo view")
		return common.NewErrCode(common.ErrGeneralError)
	}

	if err := common.DB(db).Transaction(func(tx *gorm.DB) error {
		if err := orm.EditTopoView(tx, param); err != nil {
			log.WithField("param", common.MustMarshal(param)).
				Error("edit topo view in database failed")
			return err
		}

		if err := cache.Instance().EditTopoView(param); err != nil {
			log.WithField("param", common.MustMarshal(param)).
				Error("edit topo view in cache failed")
		}
		return nil
	}); err != nil {
		log.Error("edit topo view failed")
		return err
	}

	return nil
}

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func DeleteTopoView(db *gorm.DB, param common.DeleteTopoViewParam) error {
	topoView, err := cache.Instance().FindTopoViewByID(param.ID)
	if err != nil {
		log.WithField("ID", param.ID).Error("cannot find topo view")
		return err
	}

	if topoView.Name == topoView.Module.Name+"-topo-view" {
		log.WithField("ID", param.ID).
			Error("cannot delete default topo view")
		return common.NewErrCode(common.ErrGeneralError)
	}

	if err := common.DB(db).Transaction(func(tx *gorm.DB) error {
		if err := orm.DeleteTopoView(tx, param); err != nil {
			log.WithField("ID", param.ID).Error("delete topo view in database failed")
			return err
		}
		if err := cache.Instance().DeleteTopoView(param.ID); err != nil {
			log.WithField("ID", param.ID).Error("delete topo view in cache failed")
			return err
		}
		return nil
	}); err != nil {
		log.Error("delete topo view failed")
		return err
	}

	return nil
}
